package com.mobile.challenge

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Intent
import android.graphics.Color
import android.graphics.Point
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.security.keystore.KeyProperties
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.ImageView
import android.widget.TextView
import android.widget.ViewSwitcher
import androidx.annotation.RequiresApi
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.Observer
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.google.gson.Gson
import com.king.base.util.SharedPreferencesUtils
import com.mobile.challenge.databinding.ActivityLoginBinding
import com.mobile.challenge.fingerprint.*
import com.mobile.challenge.fingerprint.FingerprintHelper.SimpleAuthenticationCallback
import com.mobile.challenge.ui.DashboardActivity
import com.mobile.challenge.ui.KeyboardHeightObserver
import com.mobile.challenge.ui.KeyboardHeightProvider
import com.mobile.challenge.util.*
import com.mobile.frame.mvvmframe.base.BaseActivity
import kotlinx.android.synthetic.main.include_login_pw.*
import java.util.regex.Pattern


class LoginActivity : BaseActivity<LoginViewModel, ActivityLoginBinding>(), KeyboardHeightObserver {

    lateinit var keyboardHeightProvider: KeyboardHeightProvider
    private var isNavBarshown = false

    private lateinit var tvLogin: TextView
    lateinit var viewSwitcher: ViewSwitcher
    lateinit var inputUsername: TextInputLayout
    lateinit var ivSwitch: ImageView
    lateinit var etUsername: TextInputEditText
    lateinit var etPassword: TextInputEditText
    lateinit var tvUsernamePw: TextView
    lateinit var tvUsernameFp: TextView
    lateinit var ivFingerprint: ImageView

    var isUsernameValid: Boolean = false
    var isPasswordValid: Boolean = false

    lateinit var keyHelper: KeyHelper

    lateinit var username: String
    lateinit var password: String
    lateinit var localUserId: String

    lateinit var cardViewlayoutParams: ConstraintLayout.LayoutParams

    private lateinit var helper: FingerprintHelper

    var isTouchIDEnrolled: Boolean = false

    override fun getLayoutId(): Int = R.layout.activity_login

    @RequiresApi(Build.VERSION_CODES.M)
    override fun onCreate(savedInstanceState: Bundle?) {
        // immersion related code
        window.clearFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                        or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
        )
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)

        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            window.statusBarColor = Color.TRANSPARENT
            window.navigationBarColor = Color.TRANSPARENT
        }

        super.onCreate(savedInstanceState)

        keyboardHeightProvider = KeyboardHeightProvider(this)
        mBinding.root.post {
            keyboardHeightProvider.start()
        }
        initVideoView()
        checkNavgationBar()
        keyHelper = KeyHelper(this)
        keyHelper.generateRandomIV(this)
        helper = FingerprintHelper.getInstance()
        helper.init(applicationContext)
    }


    @RequiresApi(Build.VERSION_CODES.M)
    override fun initData(savedInstanceState: Bundle?) {
        tvLogin = mBinding.tvLogin
        viewSwitcher = mBinding.viewSwitcher
        inputUsername = mBinding.loginPwLayout.inputUserName
        ivSwitch = mBinding.ivSwitch
        etUsername = mBinding.loginPwLayout.etUsername
        etPassword = mBinding.loginPwLayout.etPassword
        tvUsernamePw = mBinding.loginPwLayout.tvUsernamePw
        tvUsernameFp = mBinding.loginFpLayout.tvUsernameFp
        ivFingerprint = mBinding.loginFpLayout.ivFingerprint

        cardViewlayoutParams = mBinding.loginMainCardView.layoutParams as ConstraintLayout.LayoutParams

        isTouchIDEnrolled = SharedPreferencesUtils.getBoolean(this, IS_TOUCH_ID_ENROLLED)
        localUserId = SharedPreferencesUtils.getString(this, USER_ID, "")

        if (localUserId.isNullOrEmpty()) {
            viewSwitcher.displayedChild = LOGIN_PW
            tvUsernamePw.visibility = View.GONE
            username = ""
        } else {
            username = localUserId
            isUsernameValid = true
            inputUsername.visibility = View.GONE
            if (isTouchIDEnrolled) {
                showFPScreeen()
            } else {
                showPWScreen()
            }
        }

        initListener()
    }

    private fun showPWScreen() {
        viewSwitcher.displayedChild = LOGIN_PW
        tvUsernamePw.visibility = View.VISIBLE
        tvUsernamePw.text = localUserId
        tvLogin.visibility = View.VISIBLE
    }

    private fun showFPScreeen() {
        viewSwitcher.displayedChild = LOGIN_FP
        ivSwitch.visibility = View.VISIBLE
        tvUsernameFp.text = localUserId
        tvLogin.visibility = View.INVISIBLE
    }

    @RequiresApi(Build.VERSION_CODES.M)
    private fun initListener() {
        etUsername.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) =
                    Unit

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit

            override fun afterTextChanged(s: Editable?) {
                inputUsername.error = ""
                text_input_password.error = ""
                s?.toString()?.apply {
                    username = this.trim()
                    isUsernameValid = checkValidation(username, USER_NAME_REGEX)
                }
                tvLogin.isEnabled = isUsernameValid && isPasswordValid
            }
        })

        etPassword.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) =
                    Unit

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit

            override fun afterTextChanged(s: Editable?) {
                inputUsername.error = ""
                text_input_password.error = ""
                s?.toString()?.apply {
                    password = this.trim()
                    isPasswordValid = checkValidation(password, PASSWORD_REGEX)
                }
                tvLogin.isEnabled = isUsernameValid && isPasswordValid
            }
        })

        mViewModel.loginData.observe(this, Observer { result ->
            hideLoading()
            // 保存用户名
            SharedPreferencesUtils.put(this, USER_ID, username)
            localUserId = username
            // 保存密码
            if (!isTouchIDEnrolled) {
                // TODO 实际需要打开
                SharedPreferencesUtils.put(this, PASSWORD, keyHelper.encrypt(this, password))
            }
            val intent = Intent(this, DashboardActivity::class.java)
            intent.putExtra("logindata", Gson().toJson(result))
            startActivity(intent)
            this.finish()
        })

        mViewModel.loginError.observe(this, Observer {
            hideLoading()
            if (viewSwitcher.displayedChild == LOGIN_PW) {
                if (it.hintMsg.isNullOrEmpty()) {
                    text_input_password.error = it.errorMsg
                } else {
                    text_input_password.error = it.hintMsg
                }
            }
        })

        tvLogin.setOnClickListener {
//            mViewModel.login("1024_UM", "123456")
            mViewModel.login(username, password)
//            inputAnimator(mBinding.loginMainCardView, mBinding.loginMainCardView.width, mBinding.loginMainCardView.height);
//            startAnimator()
            showLoading()
//            start(DashboardActivity::class.java)
        }

        mBinding.ivSwitch.setOnClickListener {
            if (viewSwitcher.displayedChild == LOGIN_FP) {
                viewSwitcher.displayedChild = LOGIN_PW
                showPWScreen()
            } else {
                viewSwitcher.displayedChild = LOGIN_FP
                etPassword.setText("")
                showFPScreeen()
            }
        }

        ivFingerprint.setOnClickListener {
            initialFingerprintHelper()
        }
    }

    private fun checkValidation(str: String, regExp: String): Boolean = Pattern.matches(regExp, str)

    private fun checkNavgationBar() {
        val display = windowManager.defaultDisplay
        val size = Point()
        val realSize = Point()
        display.getSize(size)
        display.getRealSize(realSize)
        // true means show
        isNavBarshown = realSize.y != size.y
    }

    fun initVideoView() {
        mBinding.videoView.setVideoURI(Uri.parse("android.resource://$packageName/raw/login_bg"))
        // Mute
        mBinding.videoView.setOnPreparedListener {
            it.setVolume(0f, 0f)
        }
        mBinding.videoView.start()
        mBinding.videoView.setOnCompletionListener {
            mBinding.videoView.start()
        }
    }

    override fun onResume() {
        super.onResume()
        keyboardHeightProvider.setKeyboardHeightObserver(this)
    }

    override fun onPause() {
        super.onPause()
        keyboardHeightProvider.setKeyboardHeightObserver(null)
    }

    override fun onRestart() {
        initVideoView()
        super.onRestart()
    }

    override fun onStop() {
        //防止锁屏或者弹出的时候，音乐在播放
        mBinding.videoView.stopPlayback()
        super.onStop()
    }

    override fun onDestroy() {
        super.onDestroy()
        keyboardHeightProvider.close()
    }

    override fun onKeyboardHeightChanged(height: Int, orientation: Int) {
        val layoutParams = mBinding.btnLogin.layoutParams as ConstraintLayout.LayoutParams
        // in some device might have a little issue
//        var navHeight = 0
//        if (isNavBarshown) {
//            navHeight = navigationBarHeight
//        }
//        val brand = android.os.Build.BRAND

        Log.e(this.TAG, "onKeyboardHeightChanged: $height ")
        if (height > 0) {
            // if we use Immersion mode ,should handle nav height and status height
            layoutParams.bottomMargin = height + navigationBarHeight + statusBarHeight
            mBinding.guideline.setGuidelinePercent(0.99f)
        } else {
            layoutParams.bottomMargin = 0
            mBinding.guideline.setGuidelinePercent(0.85f)
        }
        mBinding.btnLogin.layoutParams = layoutParams
    }


    private lateinit var fingerprintVerifyDialog: FingerprintVerifyDialog
    private var fingerprintChangeTipDialog: CommonTipDialog? = null

    @RequiresApi(api = Build.VERSION_CODES.M)
    fun initialFingerprintHelper() {
        //验证指纹库信息是否发生变化
        if (FingerprintUtil.isLocalFingerprintInfoChange(context)) {
            //指纹库信息发生变化
            showFingerprintChangeTipDialog()
            return
        }

        helper.setPurpose(KeyProperties.PURPOSE_DECRYPT)
        helper.authenticate()

        helper.setCallback(object : SimpleAuthenticationCallback {
            override fun onAuthenticationSucceeded(value: String) {
                Log.e("hagan", "FingerprintLoginFragment->onAuthenticationSucceeded-> value:$value")
                val decodePassword = keyHelper.decrypt(this@LoginActivity, SharedPreferencesUtils.getString(this@LoginActivity, PASSWORD, ""))
                if (decodePassword.isNotEmpty()) {
                    password = decodePassword
//                     TODO mViewModel.login(localUserId, password)
                    mViewModel.login(username, password)
                    showLoading()
                }
            }

            override fun onAuthenticationFail() {
                Log.e("hagan", "HomeActivity->onAuthenticationFail")
            }

            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                Log.e("hagan", "HomeActivity->onAuthenticationError-> errorCode:$errorCode,errString:$errString")
                Snackbar.make(mBinding.root, errString, Snackbar.LENGTH_SHORT).show()
            }

            override fun onAuthenticationHelp(helpCode: Int, helpString: CharSequence) {
                Log.e("hagan", "HomeActivity->onAuthenticationHelp-> helpCode:$helpCode,helpString:$helpString")
            }
        })
    }

    private fun showFingerprintChangeTipDialog() {
        if (fingerprintChangeTipDialog == null) {
            fingerprintChangeTipDialog = CommonTipDialog(this)
        }
        fingerprintChangeTipDialog?.apply {
            this.setContentText(resources.getString(R.string.fingerprintChangeTip))
            this.setSingleButton(true)
            this.setOnSingleConfirmButtonClickListener { }
            this.show()
        }

    }

    fun startAnimator() {
        mBinding.loginMainCardView.isEnabled = false
        mBinding.loginMainCardView.isFocusableInTouchMode = false
        val alpha: ObjectAnimator = ObjectAnimator.ofFloat(mBinding.loginMainCardView,
                "alpha", 0.9f, 0f)
        alpha.duration = 200
        alpha.start()
        alpha.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator?) {
            }

            override fun onAnimationEnd(animation: Animator?) {
                mBinding.ivLoading.visibility = View.VISIBLE
            }

            override fun onAnimationCancel(animation: Animator?) {
            }

            override fun onAnimationRepeat(animation: Animator?) {
            }

        })
    }

    fun endAnimator() {
        mBinding.loginMainCardView.alpha = 0.9f

    }

    private fun inputAnimator(view: View, width: Int, height: Int) {
        val set = AnimatorSet()
        val widthAnimater = ValueAnimator.ofInt(width, view.dp2px(50F))
        widthAnimater.addUpdateListener {
            val params: ViewGroup.MarginLayoutParams = view
                    .layoutParams as ViewGroup.MarginLayoutParams
            params.width = it.animatedValue as Int
            view.layoutParams = params
        }

        val heightAnimater = ValueAnimator.ofInt(height, view.dp2px(50F))
        heightAnimater.addUpdateListener {
            val params: ViewGroup.MarginLayoutParams = view
                    .layoutParams as ViewGroup.MarginLayoutParams
            params.height = it.animatedValue as Int
            view.layoutParams = params
        }

        val rotation: ObjectAnimator = ObjectAnimator.ofFloat(mBinding.loginMainCardView,
                "rotation", 0f, 36000f)
        rotation.duration = 2000
        set.duration = 500
        set.interpolator = AccelerateDecelerateInterpolator()
        set.playTogether(widthAnimater, heightAnimater)
        set.start()
        set.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator?) {}
            override fun onAnimationRepeat(animation: Animator?) {}
            override fun onAnimationEnd(animation: Animator?) {
                /**
                 * 动画结束后，先显示加载的动画，然后再隐藏输入框
                 */
//                progress.setVisibility(View.VISIBLE)
//                progressAnimator(progress)
                mBinding.loginMainCardView.visibility = View.INVISIBLE
//                rotation.start()
            }

            override fun onAnimationCancel(animation: Animator?) {}
        })
    }
}
